﻿using BCCommon.Enums;
using BCCommon.OAEnums;
using BCData.OA.TeamWorks.TaskRecord;
using BCData.OA.Workflow.WorkflowActivity;
using BCData.OA.Workflow.WorkflowActivityInstanceBusiness;
using BCData.OA.Workflow.WorkflowActivityStep;
using BCData.OA.Workflow.WorkflowActivityStepExtendMethod;
using BCDto.OA.Workflow.WorkflowOperation;
using BCEntity.OA.Workflow.WorkflowActivity;
using BCEntity.OA.Workflow.WorkflowActivityInstance;
using BCEntity.OA.Workflow.WorkflowActivityStep;
using BCEntity.OA.Workflow.WorkflowActivityStepExtendMethod;
using BCEntity.OA.Workflow.WorkflowActivityStepExtendMethodInstance;
using BCEntity.OA.Workflow.WorkflowActivityStepInstance;
using BCService.OA.WorkflowEngine.WorkflowRunning;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BCService.OA.WorkflowEngine
{
    public class WorkflowEngineService : IWorkflowEngineService
    {
        private readonly IApplicationContextService applicationContextService;
        private readonly IWorkflowActivityData workflowActivityData;
        private readonly IWorkflowActivityStepData workflowActivityStepData;
        private readonly IWorkflowActivityStepExtendMethodData workflowActivityStepExtendMethodData;
        private readonly IWorkflowActivityInstanceBusinessData workflowActivityInstanceBusinessData;
        private readonly IWorkflowRunningService workflowRunningService;
        private readonly ITaskRecordData taskRecordData;

        public WorkflowEngineService(IApplicationContextService applicationContextService,
            IWorkflowActivityData workflowActivityData,
            IWorkflowActivityStepData workflowActivityStepData,
            IWorkflowActivityStepExtendMethodData workflowActivityStepExtendMethodData,
            IWorkflowActivityInstanceBusinessData workflowActivityInstanceBusinessData,
            IWorkflowRunningService workflowRunningService,
            ITaskRecordData taskRecordData)
        {
            this.applicationContextService = applicationContextService;
            this.workflowActivityData = workflowActivityData;
            this.workflowActivityStepData = workflowActivityStepData;
            this.workflowActivityStepExtendMethodData = workflowActivityStepExtendMethodData;
            this.workflowActivityInstanceBusinessData = workflowActivityInstanceBusinessData;
            this.workflowRunningService = workflowRunningService;
            this.taskRecordData = taskRecordData;
        }

        #region 初始化工作流活动实例
        public long InitWorkflowActivityInstance(string workflowKey, int companyId, bool isTemplateActivity, RoleType roleType, ref string instanceNo)
        {
            WorkflowActivityEntity workflowActivityEntity = this.workflowActivityData.GetEntity(workflowKey).GetAwaiter().GetResult();
            if (workflowActivityEntity == null)
            {
                throw new ArgumentException("此工作流活动不存在");
            }

            instanceNo = Guid.NewGuid().ToString();

            IEnumerable<WorkflowActivityStepEntity> workflowActivityStepEntities = this.workflowActivityStepData.Get(workflowActivityEntity.WorkflowActivityId).GetAwaiter().GetResult();

            List<WorkflowActivityStepInstanceEntity> stepInstanceEntities = new List<WorkflowActivityStepInstanceEntity>();
            foreach (WorkflowActivityStepEntity stepEntity in workflowActivityStepEntities)
            {
                WorkflowActivityStepInstanceEntity instanceStepEntity = new WorkflowActivityStepInstanceEntity()
                {
                    WorkflowActivityInstanceNo = instanceNo,
                    TaskStep = stepEntity.TaskStep,
                    ParentStep = stepEntity.ParentStep,
                    StepName = stepEntity.StepName,
                    AssignBased = stepEntity.AssignBased,
                    AssignMode = stepEntity.AssignMode,
                    TaskMethodTitle = stepEntity.TaskMethodTitle,
                    TaskServiceName = stepEntity.TaskServiceName,
                    TaskMethodName = stepEntity.TaskMethodName,
                    TaskMethodParameters = stepEntity.TaskMethodParameters,
                    DepartmentId = stepEntity.DepartmentId,
                    IsBaseHandleMode = stepEntity.IsBaseHandleMode,
                    AdminId = stepEntity.AdminId,
                    Role = stepEntity.Role,
                    WorkingGroupId = stepEntity.WorkingGroupId,
                    Position = stepEntity.Position,
                    StepType = stepEntity.StepType,
                    RoleType = stepEntity.RoleType,
                };
                stepInstanceEntities.Add(instanceStepEntity);
            }
            workflowActivityEntity.Steps = workflowActivityStepEntities.ToList();

            IEnumerable<WorkflowActivityStepExtendMethodEntity> extentdMethodEntities = this.workflowActivityStepExtendMethodData.Get(workflowActivityEntity.WorkflowActivityId).GetAwaiter().GetResult();
            List<WorkflowActivityStepExtendMethodInstanceEntity> extendMethodInstanceEntities = new List<WorkflowActivityStepExtendMethodInstanceEntity>();
            foreach (var methodEntity in extentdMethodEntities)
            {
                WorkflowActivityStepExtendMethodInstanceEntity extendMethodInstanceEntity = new WorkflowActivityStepExtendMethodInstanceEntity()
                {
                    WorkflowActivityInstanceNo = instanceNo,
                    TaskStep = methodEntity.TaskStep,
                    ExtendMethodCode = methodEntity.ExtendMethodCode,
                    ExtendMethodName = methodEntity.ExtendMethodName,
                    ExtendMethodTitle = methodEntity.ExtendMethodTitle,
                    TaskMethodName = methodEntity.TaskMethodName,
                    TaskServiceName = methodEntity.TaskServiceName,
                    TaskMethodParameters = methodEntity.TaskMethodParameters,
                    IsCustom = methodEntity.IsCustom,
                    GotoStep = methodEntity.GotoStep

                };
                extendMethodInstanceEntities.Add(extendMethodInstanceEntity);
            }
            workflowActivityEntity.ExtendMethods = extentdMethodEntities.ToList();

            WorkflowActivityInstanceEntity instanceEntity = new WorkflowActivityInstanceEntity()
            {
                CompanyId = companyId,
                WorkflowActivityInstanceNo = instanceNo,
                WorkflowActivityId = workflowActivityEntity.WorkflowActivityId,
                WorkflowKey = workflowActivityEntity.WorkflowKey,
                WorkflowType = workflowActivityEntity.WorkflowType,
                WorkflowName = workflowActivityEntity.WorkflowName,
                TotalStep = workflowActivityEntity.Steps.Count,
                IsTemplateActivity = isTemplateActivity,
                IsBaseWorkflow = workflowActivityEntity.IsBaseWorkflow,
                CurrentlyStep = 0,
                Steps = stepInstanceEntities,
                AuthorAdminId = applicationContextService.Admin.AdminId,
                AuthorFullName = applicationContextService.Admin.FullName,
                ExtendMethods = extendMethodInstanceEntities,
                RoleType = roleType
            };
            if (!this.workflowActivityInstanceBusinessData.Add(instanceEntity).GetAwaiter().GetResult())
            {
                throw new ArgumentException("创建工作流活动实例失败");
            }
            long instanceId = this.workflowActivityInstanceBusinessData.GetId(instanceNo).GetAwaiter().GetResult();
            if (!this.workflowActivityInstanceBusinessData.UpdateWorkflowActivityInstanceId(instanceNo, instanceId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("创建实例成功，修改工作流活动步骤实例Id失败：" + instanceNo);
            }

            return instanceId;
        }
        #endregion

        #region 下一步
        public void NextStep(long workflowActivityInstanceId)
        {
            this.workflowActivityInstanceBusinessData.UpdateWorkflowActivityCurrentlyStepNext(workflowActivityInstanceId);
        }
        #endregion

        #region 上一步
        public void PreviousStep(long workflowActivityInstanceId)
        {
            this.workflowActivityInstanceBusinessData.UpdateWorkflowActivityCurrentlyStepPrevious(workflowActivityInstanceId);
        }
        #endregion

        #region 工作流处理操作
        public void Execution(WorkflowOperationRequestDto workflowOperationRequestDto)
        {
            if (workflowOperationRequestDto.HandleStatus == OATaskHandleOperationStatus.Rejected && string.IsNullOrWhiteSpace(workflowOperationRequestDto.Remark))
            {
                throw new ArgumentException("驳回备注不能为空");
            }
            //检查任务是否已处理
            var taskRecord = this.taskRecordData.GetEntity(workflowOperationRequestDto.TaskRecordNo).GetAwaiter().GetResult();
            if (taskRecord != null && (taskRecord.HandleStatus == OATaskHandleStatus.Handled || taskRecord.HandleStatus == OATaskHandleStatus.Closed || taskRecord.HandleStatus == OATaskHandleStatus.Dismissed))
            {
                throw new ArgumentException("任务已处理，不能重复处理");
            }
            this.workflowRunningService.Execution(workflowOperationRequestDto);
        }
        #endregion

        #region 工作流分配
        private void Assigning(long workflowActivityInstanceId)
        {
            this.workflowRunningService.Assigning(workflowActivityInstanceId);
        }
        #endregion

        #region 开始工作流
        public void Start(long workflowActivityInstanceId)
        {
            this.workflowRunningService.StartRunning(workflowActivityInstanceId);
        }

        public void StateReady()
        {
            var workflowActivityInstanceEntities = this.workflowActivityInstanceBusinessData.GetReadyActivity().GetAwaiter().GetResult();

            foreach (var entity in workflowActivityInstanceEntities)
            {
                this.workflowRunningService.StartRunning(entity.WorkflowActivityInstanceId);
            }
        }
        #endregion
    }
}
